package com.le.tester.javaThink.fourth.concurrency;

import java.io.PrintWriter;
import java.sql.SQLOutput;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * createTime：2021/12/22 14:49
 * description：toast自动化
 */


class Toast {
    public enum Status {DRY, BUTTERED, JAMMED}

    //给定一个默认的状态
    private Status status = Status.DRY;
    private final int id;

    public Toast(int id) {
        this.id = id;
    }

    //面包的状态变成黄油
    public void butter() {
        status = Status.BUTTERED;
    }

    //面包的状态变成果酱
    public void jam() {
        status = Status.JAMMED;
    }


    public Status getStatus() {
        return status;
    }

    public int getId() {
        return id;
    }

    @Override
    public String toString() {
        return "Toast{" +
                "status=" + status +
                ", id=" + id +
                '}';
    }
}

//链表阻塞队列，隐式的解决了异步的问题，有顺序的put和take
class ToastQueue extends LinkedBlockingQueue<Toast> {
}

class Toaster implements Runnable {

    private ToastQueue toastQueue;

    private int count = 0;

    private Random random = new Random(47);

    public Toaster(ToastQueue toastQueue) {
        this.toastQueue = toastQueue;
    }

    @Override
    public void run() {
        try {
            while (!Thread.interrupted()) {
                TimeUnit.MILLISECONDS.sleep(100 + random.nextInt(500));
                Toast toast = new Toast(count++);
                //打印toString()过后的日志
                System.out.println(toast);
                //在该线程没有中断的情况下，将new toast一直放进队列
                toastQueue.put(toast);
            }
        } catch (Exception e) {
            System.out.println("Toast queue interrupted");
        }
        System.out.println("Toaster off");
    }
}

class Butterer implements Runnable {

    private ToastQueue dryQueue, buttteredQueue;

    public Butterer(ToastQueue dryQueue, ToastQueue buttteredQueue) {
        this.dryQueue = dryQueue;
        this.buttteredQueue = buttteredQueue;
    }

    @Override
    public void run() {
        try {
            while (!Thread.interrupted()) {
                Toast dryToast = dryQueue.take();
                dryToast.butter();
                System.out.println(dryToast);
                //都是涂上了黄油的toast
                buttteredQueue.put(dryToast);
            }
        } catch (Exception e) {
            System.out.println("Butterer interrupted");
        }
        System.out.println("Butterer off");
    }
}

class Jammer implements Runnable {

    private ToastQueue butteredQueue, finishedQueue;

    public Jammer(ToastQueue butteredQueue, ToastQueue finishedQueue) {
        this.butteredQueue = butteredQueue;
        this.finishedQueue = finishedQueue;
    }

    @Override
    public void run() {
        try {
            while (!Thread.interrupted()) {
                Toast butterToast = butteredQueue.take();
                butterToast.jam();
                System.out.println(butterToast);
                finishedQueue.put(butterToast);
            }
        } catch (Exception e) {
            System.out.println("Jammer interrupted");
        }
        System.out.println("Jammer off");
    }
}

class Eater implements Runnable {

    private ToastQueue finishedQueue;

    private int counter = 0;

    public Eater(ToastQueue finishedQueue) {
        this.finishedQueue = finishedQueue;
    }

    @Override
    public void run() {
        try {
            while (!Thread.interrupted()) {
                Toast finishedToast = finishedQueue.take();
                if (finishedToast.getId() != counter++ || finishedToast.getStatus() != Toast.Status.JAMMED) {
                    System.out.println(">>>>>> Error: " + finishedToast);
                    System.exit(1);
                } else {
                    System.out.println("Chomp!" + finishedToast);
                }
            }
        } catch (Exception e) {
            System.out.println("Eater interrupted");
        }
        System.out.println("Eater off");
    }
}

public class ToastOMatic {
    public static void main(String[] args) throws InterruptedException {
        ToastQueue dryQueue = new ToastQueue();
        ToastQueue buttereredQueue = new ToastQueue();
        ToastQueue finishedQueue = new ToastQueue();

        ExecutorService exec = Executors.newCachedThreadPool();
        exec.execute(new Toaster(dryQueue));
        exec.execute(new Butterer(dryQueue, buttereredQueue));
        exec.execute(new Jammer(buttereredQueue, finishedQueue));
        exec.execute(new Eater(finishedQueue));

        TimeUnit.SECONDS.sleep(5);
        exec.shutdownNow();
    }
}
